﻿using Awsc.DataAcquisitionSys.Core.DataAcquisition;
using Awsc.DataAcquisitionSys.Core.Model.Config;
using Awsc.DataAcquisitionSys.Core.Models.ServiceModels;
using Awsc.DataAcquisitionSys.Core.Services.DataAcquisition.DataCollectors;
using Awsc.DataAcquisitionSys.Core.Services.DataAcquisition.DataCollectors.Sensors;
using System.Collections.Concurrent;
using System.Xml.Linq;

namespace Awsc.DataAcquisitionSys.Core.Service.DataAcquisition.DataCollectors
{
    public abstract class DataCollector : IDataCollector
    {
        private ConcurrentBag<Sensor> _sensors = new ConcurrentBag<Sensor>();
        private readonly DataCollectionContext dataCollectionContext;
        public DataCollector(DataCollectionContext dataCollectionContext)
        {
            this.dataCollectionContext = dataCollectionContext;
            CollectorConfig = dataCollectionContext.CollectorConfig;
            InitSensorList(dataCollectionContext.CollectorConfig);

        }

        private void InitSensorList(CollectorConfig collectorConfig)
        {

            foreach (var item in collectorConfig.AllSensorConfigs)
            {
                if(item.Name=="悬重")
                {

                }
                var sensor = SensorFactory.GetSensor(dataCollectionContext, collectorConfig,item);
                sensor.Name = item.Name;
                sensor.SensorConfig = item;
                sensor.DataCollector = this;
                sensor.CollectorChannelId = item.CollectorChannelId;
                _sensors.Add(sensor);
            }
            GlobalDeviceManager.Instance.AddCollector(this);
        }

        public IEnumerable<Sensor> Sensors
        {
            get
            {
                return this._sensors;
            }
        }
        public Sensor GetSensorByName(string name)
        {
            return _sensors.FirstOrDefault(s => s.Name == name);
        }
        public Sensor GetAIRegisterByChannelId(int channelId)
        {
            return _sensors.FirstOrDefault(s => s.CollectorChannelId == channelId && s.IsAIRegister);
        }
        public Sensor GetAORegisterByChannelId(int channelId)
        {
            return _sensors.FirstOrDefault(s => s.CollectorChannelId == channelId && s.IsAORegister);
        }

        public Sensor GetDICoilByChannelId(int channelId)
        {
            return _sensors.FirstOrDefault(s => s.CollectorChannelId == channelId && s.IsDICoil);
        }
        public Sensor GetDOCoilByChannelId(int channelId)
        {
            return _sensors.FirstOrDefault(s => s.CollectorChannelId == channelId && s.IsDOCoil);
        }

        public void SetAISensorValue(int channelId, double value, DevStatus status = DevStatus.S_OK)
        {
            var sensor = GetAIRegisterByChannelId(channelId);
            if (sensor == null)
            {
                return;
            }

            sensor.OutputValue = value;
            sensor.Status = status;

            if (sensor.NeedCreateAICoil)
            {
                var coil = GetSensorByName(sensor.Name + "Coil");
                if (coil != null)
                {
                    var registerConfig = sensor.SensorConfig as RegisterConfig;
                    coil.OutputValue = value >= registerConfig.OpenValue;
                    coil.Status = status;
                }
            }
        }

        public void SetAOSensorValue(int channelId, double value, DevStatus status = DevStatus.S_OK)
        {
            var sensor = GetAIRegisterByChannelId(channelId);
            if (sensor != null)
            {
                sensor.OutputValue = value;
                sensor.Status = status;
            }
        }

        public void SetDICoilValue(int channelId, bool value, DevStatus status = DevStatus.S_OK)
        {
            var sensor = GetDICoilByChannelId(channelId);
            if (sensor != null)
            {
                var config = sensor.SensorConfig as CoilConfig;
                sensor.OutputValue = config.BeReverse ? !value : value;
                sensor.Status = status;
            }
        }
        public void SetDOCoilValue(int channelId, bool value, DevStatus status = DevStatus.S_OK)
        {
            var sensor = GetDOCoilByChannelId(channelId);
            if (sensor != null)
            {
                var config = sensor.SensorConfig as CoilConfig;
                sensor.OutputValue = config.BeReverse ? !value : value;
                sensor.Status = status;
            }
        }


        Thread DataCollectThread = null;
        AutoResetEvent AutoResetEvent;


        public CollectorConfig CollectorConfig { get; set; }
        public DevStatus Status { get; set; }


        public abstract Task CollectSensorDataAsync();


        public async Task StartDataCollectionAsync()
        {
            AutoResetEvent = new AutoResetEvent(false);
            DataCollectThread = new Thread(async () => await DataCollectionAsync());
            DataCollectThread.Start();
        }
        public async Task StopDataCollectionAsync()
        {
            if (AutoResetEvent != null)
            {
                AutoResetEvent.Set();
            }
            CloseConnection();
            AutoResetEvent = null;
        }




        public abstract void CloseConnection();
        public abstract void Connect();

        private async Task DataCollectionAsync()
        {
            while (AutoResetEvent != null && !AutoResetEvent.WaitOne(CollectorConfig.UpdateFreq))
            {
                try
                {
                    await CollectSensorDataAsync();

                }
                catch (Exception ex)
                {

                }
            }
            AutoResetEvent = null;
        }


    }
}
